`ifndef __BUNDLE_SVH__
`define __BUNDLE_SVH__

`define WORD_BITS 64
typedef logic [`WORD_BITS-1:0] word_t;

typedef enum logic [2:0] {
  BT_None = 3'b000,
  BT_Branch = 3'b001,
  BT_Jump = 3'b010,
  BT_Call = 3'b011,
  BT_Ret = 3'b100,
  BT_CallRet = 3'b101
} BranchType;

typedef enum logic [4:0] {
  FU_ALU  = 'b1,
  FU_BRU  = 'b10,
  FU_LSU  = 'b100,
  FU_MDU  = 'b1000,
  FU_MISC = 'b10000
} FU_Type;

typedef enum logic [2:0] {
  FU_ALU_BIT  = 'h0,
  FU_BRU_BIT  = 'h1,
  FU_LSU_BIT  = 'h2,
  FU_MDU_BIT  = 'h3,
  FU_MISC_BIT = 'h4
} FU_Type_Bit;

typedef logic [6:0] FU_OP;

typedef enum FU_OP {
  //RV32I
  ALU_ADD,
  ALU_SUB,
  ALU_AND,
  ALU_OR,
  ALU_XOR,
  ALU_SLL,
  ALU_SRA,
  ALU_SRL,
  ALU_SLT,
  ALU_SLTU
} ALU_OP;

typedef enum FU_OP {  //RV32I
  BRU_BEQ,
  BRU_BGE,
  BRU_BGEU,
  BRU_BLT,
  BRU_BLTU,
  BRU_BNE,
  BRU_JAL,
  BRU_JALR
} BRU_OP;

typedef enum FU_OP {
  //RV32I
  LSU_LB,
  LSU_LBU,
  LSU_LH,
  LSU_LHU,
  LSU_LW,
  LSU_SB,
  LSU_SH,
  LSU_SW,
  //RV64I
  LSU_LD,
  LSU_LWU,
  LSU_SD
} LSU_OP;

typedef enum FU_OP {
  //RV32M
  MDU_DIV,
  MDU_DIVU,
  MDU_REMU,
  MDU_REM,
  MDU_MUL,
  MDU_MULH,
  MDU_MULHSU,
  MDU_MULHU
} MDU_OP;

typedef enum FU_OP {
  MISC_CSRRW,
  MISC_CSRRS,
  MISC_CSRRC,
  MISC_CSRRWI,
  MISC_CSRRSI,
  MISC_CSRRCI,
  MISC_MRET,
  MISC_EBREAK,
  MISC_ECALL,
  MISC_UNSUPPORT_OP
} MISC_OP;

typedef logic [11:0] CSR_ADDR;

typedef struct packed {logic [`WORD_BITS-1:0] pc;} IRAM_Req;

typedef struct packed {logic [`IRAM_WIDTH-1:0][31:0] inst;} IRAM_Rsp;

typedef enum logic [1:0] {
  SRC_ZERO,
  SRC_REG,
  SRC_IMM,
  SRC_PC
} SRC_Type;

typedef struct packed {
  logic taken;
  logic [`WORD_BITS-1:0] target;
  BranchType branch_type;

  logic ras_valid;
  logic [`RAS_AW-1:0] ras_pointer;
  logic [`WORD_BITS-1:0] ras_top;
  logic [`RAS_AW:0] ras_top_num;
  logic [1:0] bi_cnt;
} BPU_Res;

typedef struct packed {
  logic signed [31:0] imm32;
  logic [4:0] rs1, rs2, rd;
  SRC_Type src1_type, src2_type;
  logic has_rd;
  FU_OP fu_op;
  FU_Type fu_type;
  logic flush_pipeline;
  logic is_op32;
  logic has_imm;
  logic illegal_inst;
  BranchType branch_type;
} DecodeOP;

typedef struct packed {
  logic [`WORD_BITS-1:0] pc;
  logic [31:0] inst;
  BPU_Res bpu_res;
  logic bpu_res_valid;
} IBUF_Entry;

typedef struct packed {
  logic [31:0] inst;
  logic [`WORD_BITS-1:0] pc;
  DecodeOP dop;
  BPU_Res bpu_res;
  logic bpu_res_valid;
} FrontendOP;

typedef logic [`PRF_AW-1:0] PRF_IDX;
typedef logic [`ARF_AW-1:0] ARF_IDX;
typedef logic [`PRF_AW:0] FREELIST_IDX;

typedef struct packed {
  FrontendOP fop;
  PRF_IDX prs1, prs2, pdst;
  PRF_IDX free_pdst;
  logic has_gc;
  FREELIST_IDX freelist_rptr;
} RenamedOP;

typedef logic [5:0] EXPT_CODE;
typedef logic [`ROB_AW-1:0] ROB_PTR;
typedef struct packed {RenamedOP rop;} ROB_Entry;


typedef struct packed {
  logic finish;
  logic issue;
  logic exeception;
  EXPT_CODE exeception_code;
  logic bpred_miss;
  logic replay;
  logic mmio;
} ROB_State;


typedef struct packed {
  logic has_gc;
  logic has_rd;
  PRF_IDX free_entry;
  logic restore_gc;
  FREELIST_IDX restore_freelist_rptr;
} COMMIT_TO_RENAME;

typedef struct packed {
  RenamedOP rop;
  ROB_PTR rob_idx;
  word_t src1, src2;
  logic src1_valid, src2_valid;
  logic src1_wakeup, src2_wakeup;
} ISSUE_OP;

typedef enum logic [0:0] {
  MEM_READ,
  MEM_WRITE
} MEM_CMD;

typedef struct packed {
  MEM_CMD cmd;
  logic sign;
  word_t addr;
  logic [3:0] size;
  word_t data;
  PRF_IDX prf_idx;
  ROB_PTR rob_idx;
  logic mmio;
  logic has_rd;
} MEM_REQ;

typedef struct packed {
  logic has_data;
  logic has_rd;
  word_t  data;
  PRF_IDX prf_idx;
  ROB_PTR rob_idx;
} MEM_RSP;

`define IMM_WORD(imm32) {{(`WORD_BITS-32){imm32[31]}},imm32}

`endif  //__BUNDLE_SVH__
